/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.fyx.secure.ejb;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.fyx.secure.controll.SecureUserFacadeLocal;
import org.fyx.secure.entity.SecureUser;
import java.util.List;
import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import org.fyx.core.context.FyxContextFactory;
import org.fyx.secure.controll.SecureGroupFacadeLocal;
import org.fyx.secure.controll.SecureRoleFacadeLocal;
import org.fyx.secure.entity.SecureGroup;
import org.fyx.secure.entity.SecureRole;

/**
 * Komponenta zodpovídající za operace související se zabezpečením systému.
 * Práci s uživatelskýmí skupinami, uživateli, ...
 * 
 * @author xljan
 */
@Stateless
public class SecureBean implements SecureLocal, SecureRemote {
    public static final String GUEST_GROUP = "Guest";
    public static final String REGISTERED_GROUP = "Registered";

    public interface Role {

        static final String CATEGORY = "Security";
        static final String USER_MANAGER = "secure_user_manager";
        static final String GROUP_MANAGER = "secure_group_manager";
    }
    @EJB
    private SecureUserFacadeLocal secureUserFacade;
    @EJB
    private SecureRoleFacadeLocal secureRoleFacade;
    @EJB
    private SecureGroupFacadeLocal secureGroupFacade;

    @Override
    public void addUser(SecureUser su) {
        try {
            su.setPasswd(getHash(su.getPasswd()));
            su.setIdUser(0);
            su.setCreateTimestamp(BigInteger.valueOf(new Date().getTime()));
            su.setSecureGroupCollection(new LinkedList<SecureGroup>());
            su.getSecureGroupCollection().add(secureGroupFacade.findByName(REGISTERED_GROUP));
            secureUserFacade.create(su);
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(SecureBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private String getHash(String t) throws NoSuchAlgorithmException {
        byte[] password = {00};
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(t.getBytes());
        password = md.digest();
        StringBuilder hexString = new StringBuilder();
        for (int i = 0; i < password.length; i++) {
            hexString.append(Integer.toHexString(0xFF & password[i]));
        }
        return hexString.toString();
    }

    @Override
    public List<SecureUser> getUsers() {
        return secureUserFacade.findAll();
    }

    @Override
    public boolean emailExists(String email) {
        List<SecureUser> users = getUsers();
        for (SecureUser secureUser : users) {
            if (secureUser.getEmail().equalsIgnoreCase(email)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void autentize(SecureUser user) throws AuthorizeFailException {
        try {
            SecureUser autUser = secureUserFacade.
                    findByUsername(user.getUsername());
            if (!autUser.getPasswd().equals(getHash(user.getPasswd()))) {
                throw new AuthorizeFailException();
            }
            FyxContextFactory.getContext().setUser(autUser);
            FyxContextFactory.getContext().setLogedIn(true);
        } catch (Exception ex){
            throw new AuthorizeFailException();
        }
    }
    
    @Override
    public void authorize(){
        SecureUser user = FyxContextFactory.getContext().getUser();
        Collection<SecureGroup> groups = user.getSecureGroupCollection();
        Set<String> roles = new HashSet<String>();
        for(SecureGroup group : groups){
            for(SecureRole role : group.getSecureRoleCollection()){
                roles.add(role.getCode());
            }
        }
        FyxContextFactory.getContext().setUserRoles(roles);
    }
    
    @Override
    public boolean authorizeRemote(SecureUser user) throws AuthorizeFailException {
        try{
            autentize(user);
        }catch(Exception ex){
            return false;
        }
        return true;
    }

    @Override
    public Set<String> autentizeRemote() {
        authorize();
        return FyxContextFactory.getContext().getUserRoles();
    }

    @Override
    public void deleteUser(SecureUser su) {
        secureUserFacade.remove(su);
        FacesContext.getCurrentInstance().addMessage(null,
                new FacesMessage("Uživatel byl odstraněn"));
    }

    @Override
    public SecureUser getUserById(int idUser) {
        return secureUserFacade.find(idUser);
    }

    @Override
    public int getCountUsers() {
        return secureUserFacade.count();
    }

    @Override
    public void addRole(SecureRole role) {
        if (secureRoleFacade.find(role.getCode()) == null) {
            secureRoleFacade.create(role);
        }
    }

    @Override
    public void logout() {
        FyxContextFactory.getContext().setLogedIn(false);
        FyxContextFactory.getContext().setUser(new SecureUser());
        Set<String> roles = new HashSet<String>();
        SecureGroup guestGroup = secureGroupFacade.findByName(GUEST_GROUP);
        for(SecureRole role : guestGroup.getSecureRoleCollection()){
            roles.add(role.getCode());
        }
        FyxContextFactory.getContext().setUserRoles(roles);
    }
}
